package com.ruoyi.cs.service.payment.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.payment.MakeTDJsonOrderReq;
import com.ruoyi.common.payment.YukuaiqiCallbackReq;
import com.ruoyi.common.payment.YukuaiqiConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.pay.HttpsUtils;
import com.ruoyi.common.utils.pay.PayjsConfig;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.cs.domain.TRecharge;
import com.ruoyi.cs.domain.TUser;
import com.ruoyi.cs.domain.TUserAuthentication;
import com.ruoyi.cs.domain.vo.SomisspayVo;
import com.ruoyi.cs.mapper.TRechargeMapper;
import com.ruoyi.cs.mapper.TUserAuthenticationMapper;
import com.ruoyi.cs.mapper.TUserMapper;
import com.ruoyi.cs.service.CommonService;
import com.ruoyi.cs.service.payment.YukuaiqiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;


@Service
@SuppressWarnings("all")
@Slf4j
public class YukuaiqiServiceImpl implements YukuaiqiService {
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private CommonService commonService;
    @Autowired
    private TRechargeMapper tRechargeMapper;
    @Value("${ruoyi.yukuaiqiNotify}")
    private String cznotify;
    @Value("${ruoyi.returnUrl}")
    private String returnUrl;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TUserAuthenticationMapper tUserAuthenticationMapper;

    @Override
    public Response<Map> recharge(String userId, BigDecimal czMoney, String czEquipment) throws Exception {
        TUser tUser = tUserMapper.selectTUserById(userId);
        TUserAuthentication tUserAuthentication = tUserAuthenticationMapper.selectTUserAuthenticationByUserId(tUser.getUserId().toString());
        if (tUserAuthentication == null){
            /**满足触发实名认证*/
            return  Response.fail("请先实名认证！");
        }
        String out_trade_no = IdUtil.fastSimpleUUID();
        String extraAccountCertnoLastSix = tUserAuthentication.getIdcard().substring(tUserAuthentication.getIdcard().length()-6);

        BigDecimal giveFee = new BigDecimal("0");
        try {
            giveFee = commonService.rechargeVerification(tUser, czMoney);
        } catch (Exception e) {
            return Response.fail(e.getMessage());
        }
        Instant instant = Instant.now();
        Long currentTimestamp = instant.getEpochSecond();

        Map<String, String> extUserInfo = new HashMap<>();
        extUserInfo.put("name",tUserAuthentication.getRealname());
        extUserInfo.put("cert_no",tUserAuthentication.getIdcard());

        MakeTDJsonOrderReq request = MakeTDJsonOrderReq.builder()
                .openid(YukuaiqiConstants.openid)
                .mchSecret(YukuaiqiConstants.mch_secret)
                .nonceStr(out_trade_no)
                .body(out_trade_no)
                .outTradeNo(out_trade_no)
                .totalFee(czMoney.toString())
                .notifyUrl(cznotify)
                .tradeType("600") // or any specific value
                .deviceInfo("app")
                .timeStamp(currentTimestamp.toString())
//                .extUserInfo(JSON.toJSONString(extUserInfo))
//                .returnUrl(returnUrl)
                .ip(IpUtils.getIpAddr(ServletUtils.getRequest()))
                .build();
        String sign = generateSignature(request);
        request.setSign(sign);
        // 创建 ObjectMapper 对象
        ObjectMapper mapper = new ObjectMapper();
        // 将对象转换为 JSON 字符串
        String jsonString = mapper.writeValueAsString(request);
        log.info("yukuaiqi支付申请参数:{}",jsonString);
        /**发送请求*/
        HttpResponse response = HttpRequest.post(YukuaiqiConstants.orderUrl)
                .header("Content-Type", "application/json")
                .body(jsonString)
                .execute();

        // 获取响应内容
        String result = response.body();
        Long endTimestamp = instant.getEpochSecond();
        log.info("yukuaiqi充值发送请求时间:{}",endTimestamp-currentTimestamp);
        JSONObject resultObject = JSON.parseObject(result);
        if("0".equals(resultObject.getString("code"))){
            return Response.fail(resultObject.getString("msg"));
        }
        String url = resultObject.getString("payUrl");
        String picurl = null;
        try {
            /**生产二维码图片*/
            picurl = commonService.scQrCodeImgeWeb(url);
        } catch (Exception e) {
            log.error("yukuaiqi支付生产二维码订单异常:{}", e.getMessage());
            e.printStackTrace();
            return Response.fail("发送请求失败");
        }

        TRecharge tRecharge = new TRecharge();
        tRecharge.setUserId(userId);
        tRecharge.setCzId(out_trade_no);
        tRecharge.setDelFlag(Constants.SUCCESS);
        tRecharge.setCzType(Constants.ALIPAY);
        tRecharge.setMerchantOrderNo(out_trade_no);
        /**支付结果  0 待充值 1充值成功 2充值失败*/
        tRecharge.setCzStatus(Constants.CZSTATUS0);
        /**交易类型*/
        tRecharge.setCzEquipment(czEquipment);
        tRecharge.setCreateTime(DateUtils.getNowDate());
        tRecharge.setGiveFee(giveFee);
        tRecharge.setCzMoney(czMoney);
        tRecharge.setCzPlatform(Constants.CZPLATFORM7);
        tRecharge.setUserType(tUser.getUserType());
        if (StringUtils.isNotEmpty(tUser.getUserPromotersId())) {
            tRecharge.setUserPromotersId(tUser.getUserPromotersId());
        }
        int count = tRechargeMapper.insertTRecharge(tRecharge);
        if (count > 0) {
            Map resultMap = new HashMap();
            resultMap.put("picUrl", picurl);
            resultMap.put("czId", out_trade_no);
            resultMap.put("totalFee", czMoney);
            resultMap.put("url", url);
            log.info("yukuaiqi支付订单生产：参数信息：{}，支付金额：{},订单号：{}", JSON.toJSONString(tRecharge), czMoney, out_trade_no);
            return Response.success(resultMap);
        } else {
            log.error("yukuaiqi支付充值记录表插入失败：参数信息：{}，支付金额：{},订单号：{}", JSON.toJSONString(tRecharge), czMoney, out_trade_no);
            return Response.fail("充值窗口异常，请联系管理员处理!");
        }
    }

    public static String generateSignature(MakeTDJsonOrderReq order) {
        StringBuilder sb = new StringBuilder();
        sb.append("body=").append(order.getBody()).append("&");
        sb.append("device_info=").append(order.getDeviceInfo()).append("&");
        sb.append("mch_secret=").append(order.getMchSecret()).append("&");
        sb.append("nonce_str=").append(order.getNonceStr()).append("&");
        sb.append("notify_url=").append(order.getNotifyUrl()).append("&");
        sb.append("openid=").append(order.getOpenid()).append("&");
        sb.append("out_trade_no=").append(order.getOutTradeNo()).append("&");
        sb.append("time_Stamp=").append(order.getTimeStamp()).append("&");
        sb.append("total_fee=").append(order.getTotalFee()).append("&");
        sb.append("trade_type=").append(order.getTradeType()).append("&");
        sb.append("key=").append(YukuaiqiConstants.key);
        log.info("yukuaiqi加密参数:{}",sb.toString());
//        // 使用MD5进行加密
//        String signature = null;
//        try {
//            MessageDigest md = MessageDigest.getInstance("MD5");
//            md.update(sb.toString().getBytes());
//            byte[] digest = md.digest();
//
//            // 将MD5结果转换为大写十六进制
//            BigInteger bigInt = new BigInteger(1, digest);
//            signature = bigInt.toString(16);
//            while (signature.length() < 32) {
//                signature = "0" + signature;
//            }
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        }
        String signature = DigestUtils.md5Hex(sb.toString());
        return signature.toUpperCase();
    }

    public String generateSign(YukuaiqiCallbackReq request) {
        // 构建待签名字符串
        String toBeSigned = "body=" + request.getBody() +
                "&mch_secret=" + request.getMchSecret() +
                "&nonce_str=" + request.getNonceStr() +
                "&openid=" + request.getOpenid() +
                "&out_trade_no=" + request.getOutTradeNo() +
                "&prepay_id=" + request.getPrepayId() +
                "&time_Stamp=" + request.getTimeStamp() +
                "&total_fee=" + request.getTotalFee() +
                "&trade_type=" + request.getTradeType() +
                "&key=" + YukuaiqiConstants.key;

        // 使用MD5进行加密，保证参数名区分大小写
        String encrypted = DigestUtils.md5Hex(toBeSigned);

        // 将MD5结果转换为大写
        return encrypted.toUpperCase();
    }


    @Override
    public String notify(YukuaiqiCallbackReq request) {
        log.info("yukuaiqi支付异步通知:{}",JSON.toJSONString(request));
        String msg = JSON.toJSONString(request);
        try {
            String sign = generateSign(request);
            if (sign.equals(request.getSign())){
                String prepay_id = request.getPrepayId();
                String out_trade_no = request.getOutTradeNo();
                TRecharge tRecharge = tRechargeMapper.selectTRechargeById(out_trade_no);
                String platform = tRecharge == null ? "" : tRecharge.getCzPlatform();
                log.info("yukuaiqi支付回调签名认证成功");
                if (tRecharge != null) {
                    if ("0000".equals(request.getCode())) {
                        if(Constants.CZSTATUS0.equals(tRecharge.getCzStatus())){
                            commonService.czSuccessHandle(tRecharge,out_trade_no, prepay_id,msg);
                        }
                        return "success";
                    }else {
                        commonService.czFailHandle(tRecharge,out_trade_no,prepay_id,msg);
                        return "success";
                    }
                } else {
                    log.error("yukuaiqi支付查询充值订单信息为空,请求参数：{}", msg);
                    return "fail";
                }
            } else {
                log.info("yukuaiqi支付回调签名认证失败，signVerified=false, paramsJson:{}", msg);
                return "fail";
            }
        } catch (Exception e) {
            log.error("yukuaiqi支付回调异常,paramsJson:{},errorMsg:{}", msg, e.getMessage());
            return "fail";
        }
    }
}
